package com.gusti.admincasa.services.impl;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.gson.Gson;
import com.gusti.admincasa.dao.IMessageDao;
import com.gusti.admincasa.dao.ITimeRegisterDao;
import com.gusti.admincasa.dao.IUserDao;
import com.gusti.admincasa.dto.TimeRegisterDto;
import com.gusti.admincasa.dto.UserDto;
import com.gusti.admincasa.model.Message;
import com.gusti.admincasa.model.TimeRegister;
import com.gusti.admincasa.model.User;
import com.gusti.admincasa.services.IAdminCasaService;
import com.gusti.admincasa.services.IFilterService;
import com.gusti.admincasa.util.AdminCasaResponse;
import com.gusti.admincasa.util.ConstantsUtil;
import com.gusti.admincasa.util.UserData;
import com.gusti.admincasa.util.DateUtil;

/**
 * 
 * @author gusti
 *
 */
@Service
public class AdminCasaService implements IAdminCasaService {

	@Autowired
	IFilterService filterService;
	@Autowired
	ITimeRegisterDao timeRegisterDao;
	@Autowired
	IMessageDao messageDao;
	@Autowired
	IUserDao userDao;

	@Transactional
	public AdminCasaResponse iamHere( String jsonData ) {
		AdminCasaResponse adminCasaResponse = new AdminCasaResponse();

		Gson gson = new Gson();
		UserData data = gson.fromJson( jsonData, UserData.class );

		//guardo los datos
		filterService.putUser( data );

		//creo usuario
		User user = createUser( data.getUserName() );

		//creo timeregister
		createTimeRegister( user, data );

		List<Message> responseMessages = findMessages( user );

		if( responseMessages.isEmpty() ) {
			adminCasaResponse.setErrorMsg( "ningun mensaje para mostrar" );
		} else {
			adminCasaResponse.setData( responseMessages );
		}

		return adminCasaResponse;
	}

	private User createUser( String name ) {
		User user = new User();

		//busco usuario
		user = userDao.findUser( name );

		if( user.isNew() ) {
			//guardo usuario
			user.setName( name );
			user.setStatus( User.ONLINE_STATUS );
			user = userDao.save( user );
		} else {
			//actualizo usuario
			user.setStatus( User.ONLINE_STATUS );
			user = userDao.update( user );
		}

		return user;
	}

	private void createTimeRegister( User user, UserData data ) {
		TimeRegister timeRegister = new TimeRegister();
		//busco timeregister
		timeRegister = timeRegisterDao.findTimeRegister( data.getUuid() );

		if( timeRegister.isNew() ) {
			//guardo timeRegister
			timeRegister.setUuid( data.getUuid() );
			timeRegister.setUser( user );
			timeRegister.setComputerName( data.getComputerName() );
			timeRegister.setStartDate( DateUtil.getDateFromTimeStamp( Long.valueOf( data.getTimeStamp() ) ) );
			timeRegister = timeRegisterDao.save( timeRegister );
		}
	}

	private List<Message> findMessages( User user ) {
		return messageDao.listMessages( user );
	}

	public AdminCasaResponse listUsers() {
		AdminCasaResponse adminCasaResponse = new AdminCasaResponse();

		//busco usuarios
		List<User> users = userDao.listUsers();

		if( users.isEmpty() ) {
			adminCasaResponse.setErrorMsg( ConstantsUtil.ERROR );
		} else {

			List<UserDto> userDtos = new ArrayList<UserDto>();

			//creo timeregister
			TimeRegister timeRegister = new TimeRegister();

			//recupero nombre, computer address, computer name
			for ( User user : users ) {
				//busco timeregister
				timeRegister = timeRegisterDao.findLastTimeRegister( user );
				userDtos.add( 
						new UserDto( 
								user.getName(), 
								user.getStatus(), 
								!timeRegister.isNew() ? timeRegister.getComputerName() : "-", 
								!timeRegister.isNew() ? DateUtil.getDateTime( timeRegister.getStartDate() ) : "-" ) 
						);
			}

			if( userDtos.isEmpty() ) {
				adminCasaResponse.setErrorMsg( ConstantsUtil.ERROR );
			} else {
				adminCasaResponse.setData( userDtos );
			}
		}

		return adminCasaResponse;
	}

	public AdminCasaResponse viewUser( String userName ) {
		AdminCasaResponse adminCasaResponse = new AdminCasaResponse();

		//busco usuario
		User user = userDao.findUser( userName );

		if( user.isNew() ) {
			adminCasaResponse.setErrorMsg( ConstantsUtil.ERROR );
		} else {

			//busco time registers
			List<TimeRegister> timeRegisters = timeRegisterDao.findTimeRegisters( user );

			List<TimeRegisterDto> timeRegisterDtos = new ArrayList<TimeRegisterDto>();

			for (TimeRegister timeRegister : timeRegisters) {
				timeRegisterDtos.add(
						new TimeRegisterDto(
								timeRegister.getComputerName() != null ? timeRegister.getComputerName() : "-",
								timeRegister.getStartDate() != null ? DateUtil.getDateTime( timeRegister.getStartDate() ) : "-",
								timeRegister.getEndDate() != null ? DateUtil.getDateTime( timeRegister.getEndDate() ) : "-" )
						);
			}

			if( timeRegisterDtos.isEmpty() ) {
				adminCasaResponse.setErrorMsg( ConstantsUtil.ERROR );
			} else {
				adminCasaResponse.setData( timeRegisterDtos );
			}

		}

		return adminCasaResponse;
	}

	@Transactional
	public AdminCasaResponse newMessage( String userName, String messageText ) {

		return newMessage( userName, messageText, null );
	}

	@Transactional
	public AdminCasaResponse newMessage( String userName, String messageText, String senderName ) {
		AdminCasaResponse adminCasaResponse = new AdminCasaResponse();

		//busco usuarios
		User user = userDao.findUser( userName );
		User senderUser = null;

		if( senderName != null ) {
			senderUser = userDao.findUser( senderName );
		}

		if( user.isNew() || ( senderUser != null && senderUser.isNew() ) ) {
			adminCasaResponse.setErrorMsg( ConstantsUtil.ERROR );
		} else {

			//creo mensaje
			Message message = new Message();
			message.setOwner( user );
			message.setSender( senderUser );
			message.setMessage( messageText );
			message.setReaded( false );
			message.setSendDate( DateUtil.createDateTime() );

			//guardo mensaje
			message = messageDao.save( message );
			
			if( message.isNew() ) {
				adminCasaResponse.setErrorMsg( ConstantsUtil.ERROR );
			} else {
				adminCasaResponse.setData( message );
			}
			
		}
		
		return adminCasaResponse;
	}

	@Transactional
	public AdminCasaResponse markAsReadMessage( long ownerId, long messageId ) {
		AdminCasaResponse adminCasaResponse = new AdminCasaResponse();

		Message message = messageDao.findMessage( messageId );
		if( message.isNew() ) {
			adminCasaResponse.setErrorMsg( ConstantsUtil.ERROR );
		} else {
			if( message.getOwnerId() == ownerId ) {
				message.setReaded( true );
				message = messageDao.update( message );
				adminCasaResponse.setData( message );
			} else {
				adminCasaResponse.setErrorMsg( ConstantsUtil.ERROR );
			}
		}

		return adminCasaResponse;
	}

}
